package gui.GLListeners;

import figuras.BSplines;
import figuras.PuntoVector;
import figuras.malla.MallaPorSplineYRevolucion;

import java.awt.Color;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.swing.JOptionPane;

import properties.Config;
import transformaciones.TAfin;
import utils.files.FileManagerFlowers;
import camaras.Camara;

import componentes.flor.Pistilo;

import constantes.Consts;

public class GLListenerPistilo extends GLListenerCurvas {

	private MallaPorSplineYRevolucion malla;
	// private Pistilo pistilo;
	private Color color;

	public GLListenerPistilo() {
		super();
		malla = null;
		componente = null;
		setColor(Color.green);
		this.glOption = GL.GL_POLYGON;
	}

	/***************************************************************************
	 * The init method *
	 * ********************************************************** Call by the
	 * GLDrawable just after the Gl-Context is * initialized. * * This method is
	 * used to : * - activate some modes like texture, light ... * - affect
	 * value to properties * - import testures, load your data ... * *
	 **************************************************************************/
	public void init(GLAutoDrawable glDrawable) {
		gl = glDrawable.getGL();

		gl.glClearColor(0.6f, 0.7f, 0.8f, 1.0f);
		// activamos iluminacion
		gl.glEnable(GL.GL_LIGHTING);
		gl.glEnable(GL.GL_LIGHT0);
		// luz0
		gl.glEnable(GL.GL_LIGHT0);
		float LuzDifusa[] = { 1.0f, 1.0f, 1.0f, 1.0f };
		gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, LuzDifusa, 0);
		float LuzAmbiente[] = { 0.3f, 0.3f, 0.3f, 1.0f };
		gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, LuzAmbiente, 0);
		float PosicionLuz0[] = new float[4];
		PosicionLuz0[0] = 25.0f;
		PosicionLuz0[1] = 25.0f;
		PosicionLuz0[2] = 0.0f;
		PosicionLuz0[3] = 1.0f;
		gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, PosicionLuz0, 0);

		// activamos materiales y suavidad
		gl.glEnable(GL.GL_COLOR_MATERIAL);
		gl.glMaterialf(GL.GL_FRONT, GL.GL_SHININESS, 0.1f);
		gl.glEnable(GL.GL_DEPTH_TEST);
		gl.glEnable(GL.GL_NORMALIZE);
		gl.glShadeModel(GL.GL_SMOOTH);

		// volumen de vista
		// N=1; F=1000;
		xRight = Consts.XRIGHT_GLL_PISTILO;
		xLeft = -xRight;
		yTop = xRight;
		yBot = -yTop;

		RatioViewPort = 1.0;
		PuntoVector eye = new PuntoVector(15, 15, 15, 1);
		PuntoVector look = new PuntoVector(0, 0, 0, 1);
		PuntoVector up = new PuntoVector(0, 1, 0, 0);
		int flag = 0;// 0 Ortogonal 1 perspectiva
		// if (camara == null)
		camara = new Camara(eye, look, up, flag, xLeft, xRight, yBot, yTop, 1,
				1000, 90, 0.5, gl, glu);

		// parte correspondiente a las texturas
		// gl.glShadeModel(GL.GL_SMOOTH); // Enable Smooth Shading
		// gl.glEnable(GL.GL_DEPTH_TEST);
		gl.glEnable(GL.GL_TEXTURE_2D);

//		File file = new File(Consts.DEFAULT_PISTILOS_FILE);
//		if (file.exists())
//			this.cargaPistilo(file);
		camara.esquina();

	}

	/***************************************************************************
	 * The display event *
	 * ****************************************************************** Here
	 * we place all the code related to the drawing of the scene. * This method
	 * is called by the drawing loop (the display method) *
	 **************************************************************************/
	public void display(GLAutoDrawable glDrawable) {
		super.display(glDrawable);

		if (malla == null) {
			gl.glPointSize(3.0f);
			for (int i = 0; i < manejadorSplines.getPuntosIntroducidos().size(); i++) {
				gl.glBegin(GL.GL_POINTS);
				gl.glVertex2d(manejadorSplines.getPuntosIntroducidos().get(i)
						.getX(), manejadorSplines.getPuntosIntroducidos()
						.get(i).getY());
				gl.glEnd();
			}

			for (BSplines b : manejadorSplines.getBsplines())
				// b.pintaConLineas(gl);
				b.pintaConPuntos(gl);
		}

		if (componente != null) {
			if (rota) {
				TAfin matriz = new TAfin(gl);
				matriz.setMatriz(matrix);
				componente.setMatriz(matriz);
			}
			componente.dibuja(glOption);
		}

		processEvents(glDrawable);
		setChanged();
		notifyObservers();
	}

	public void limpiaCurvas() {
		super.limpiaCurvas();
		malla = null;
		// pistilo=null;
		componente = null;
	}

	public void setColor(Color color) {
		this.color = color;
		if (componente != null)
			componente.setColor(color);
	}

	public void revolucion() {
		// if(manejadorSplines.getBsplines().size()>0){
		try {
			// ArrayList<PuntoVector> puntosControl = manejadorSplines
			// .getBsplines().get(0).getPuntosControl();
			ArrayList<PuntoVector> perfil = this.manejadorSplines.getBsplines()
					.get(0).getPerfil();
			if (perfil.get(0).getY() > perfil.get(perfil.size() - 1).getY()) {
				PuntoVector origen = new PuntoVector(0, 0, 0, 1);
				PuntoVector puntoBase = perfil.get(perfil.size() - 1);
				PuntoVector trasladaOrigen = puntoBase.obtenVector(origen);
				for (PuntoVector p : perfil) {
					p.setX(p.getX() + trasladaOrigen.getX());
					p.setY(p.getY() + trasladaOrigen.getY());
					p.setZ(p.getZ() + trasladaOrigen.getZ());
				}
				Config config = Config.getInstance();
				double radianes = config.getDouble("pistilo.radianes.revolucion");
				int pasos = config.getInteger("pistilo.pasos.revolucion");
				malla = new MallaPorSplineYRevolucion(manejadorSplines
						.getBsplines().get(0),radianes,pasos, true);
				componente = new Pistilo(malla, this.manejadorSplines
						.getBsplines(), gl);
				componente.setColor(color);
			} else {
				JOptionPane.showMessageDialog(null,
						"Dibuje el pistilo de arriba a abajo",
						"Vuelva a dibujar", JOptionPane.INFORMATION_MESSAGE);
				this.limpiaCurvas();
			}
		} catch (java.lang.IndexOutOfBoundsException e) {
			JOptionPane.showMessageDialog(null, "Introduzca una spline",
					"Spline no introducida", JOptionPane.WARNING_MESSAGE);
		} catch (IOException e) {
			JOptionPane.showMessageDialog(null, "Error",
					"Error creand spline", JOptionPane.ERROR_MESSAGE);
		}
		//camara.esquina();
		camara.frontal();
		ejeXY = true;
	}

	public void guardaPistilo(File file) {
		try {
			if (componente != null) {
				((Pistilo) componente).guardar(file);
			}
		} catch (FileNotFoundException e) {
			JOptionPane.showMessageDialog(null, "Archivo no encontrado",
					"Error", JOptionPane.ERROR_MESSAGE);
		} catch (IOException e) {
			JOptionPane.showMessageDialog(null, "Error al guardar", "Error",
					JOptionPane.ERROR_MESSAGE);
		} catch (java.lang.IndexOutOfBoundsException e) {
			JOptionPane.showMessageDialog(null, "Introduzca una spline",
					"Spline no introducida", JOptionPane.WARNING_MESSAGE);
		} finally {
			ejeXY = true;
			camara.frontal();
		}
	}

	public void cargaPistilo(File file) {
		try {
			componente = new Pistilo(gl, file);
			this.manejadorSplines.setBsplines(componente.getBsplines());
			malla = (MallaPorSplineYRevolucion) componente.getMalla();
			this.color = componente.getColor();
			camara.esquina();
		} catch (FileNotFoundException e) {
			JOptionPane.showMessageDialog(null, "Archivo no encontrado",
					"Error", JOptionPane.ERROR_MESSAGE);
		} catch (IOException e) {
			JOptionPane.showMessageDialog(null, "Error al cargar", "Error",
					JOptionPane.ERROR_MESSAGE);
		}
	}

	public void save(String path) {
		super.save(path);
		if (texturePath != null) {
			FileManagerFlowers.copyFile(texturePath, path
					+ texturePath.substring(texturePath.indexOf("."),
							texturePath.length()));
		}
		// ((Pistilo)componente).save(path);
		this.guardaPistilo(new File(path));
	}

	public void saveToAsciiPLY(String filePath) {
		if (componente != null) {
			componente.saveToAsciiPLY(filePath);
		}
	}

	public void saveToBinaryPLY(String filePath) {
		if (componente != null) {
			componente.saveToBinaryPLY(filePath);
		}
	}

	public void setTexture() {
		((Pistilo) componente).setTexture(texture);
	}
}
